import pandas as pd
from dataclasses import dataclass, asdict
from typing import List, Dict, Any, Type, Optional, Callable
from http_post import send_post_request


@dataclass
class ExcelRow:
    """Excel行数据的基础表示类"""
    data: Dict[str, Any]

    def __getattr__(self, name: str) -> Any:
        """允许通过属性名访问数据"""
        return self.data.get(name)

    def __repr__(self) -> str:
        """对象的字符串表示"""
        return f"{self.__class__.__name__}({', '.join(f'{k}={v}' for k, v in self.data.items())})"

def flatten_to_nested(item):
    nested = {}
    for key, value in item.items():
        if pd.isna(value):  # 处理空值
            continue
        keys = key.split(".")  # 拆分键名，如 ["user", "address", "city"]
        current = nested
        for part in keys[:-1]:  # 遍历前缀键，创建嵌套层级
            current = current.setdefault(part, {})
        # 最后一个键对应值
        last_key = keys[-1]
        # 处理列表（若值是逗号分隔的字符串，转为列表）
        if isinstance(value, str) and "," in value:
            current[last_key] = value.split(",")
        else:
            current[last_key] = value
    return nested

def flatten_to_nested2(item):
    """将展平的点分隔键转换为嵌套字典"""
    nested = {}
    for key, value in item.items():
        if pd.isna(value):  # 跳过空值
            continue
        parts = key.split(".")
        current = nested
        for part in parts[:-1]:
            current = current.setdefault(part, {})
        current[parts[-1]] = value
    return nested

from collections import defaultdict


def group_multiple_arrays(rows, array_keys):
    """
    处理多个嵌套数组字段

    参数:
        rows: Excel 读取的原始数据行
        array_keys: 数组字段名列表（如 ["商品列表", "物流信息"]）

    返回:
        聚合后的嵌套数据
    """
    # 按优先级排序数组键（先处理外层数组）
    array_keys = sorted(array_keys, key=lambda x: len(x.split('.')), reverse=True)

    for array_key in array_keys:
        rows = group_array_items(rows, array_key)

    return rows


def group_array_items(rows, array_key):
    """将指定数组字段的数据聚合为列表"""
    grouped = defaultdict(lambda: defaultdict(list))
    parent_id_counter = 0  # 用于生成唯一ID

    for row in rows:
        # 提取父级数据（非数组列）
        parent_data = {k: v for k, v in row.items() if not k.startswith(f"{array_key}.")}

        # 提取子级数据（数组列）
        child_data = {}
        for key, value in row.items():
            if key.startswith(f"{array_key}."):
                # 移除前缀和点号，获取子级键名
                child_key = key[len(array_key) + 1:]
                child_data[child_key] = value

        # 生成唯一标识父级的键
        # parent_key = tuple(sorted(parent_data.items()))
        # 生成唯一父级ID（改用计数器，避免不可哈希类型问题）
        parent_id = f"parent_{parent_id_counter}"
        parent_id_counter += 1

        # 将子级数据添加到对应父级的数组中
        # grouped[parent_key]["parent"] = parent_data
        # grouped[parent_key]["children"].append(child_data)

        grouped[parent_id]["parent"] = parent_data
        grouped[parent_id]["children"].append(child_data)

    # 转换为最终格式
    return [
        {**group["parent"], array_key: group["children"]}
        for group in grouped.values()
    ]

def group_array_items2(rows, array_key_prefix):
    """
    将多行数据按父级分组，并将子级数据聚合为数组

    参数:
        rows: 从 Excel 读取的字典列表
        array_key_prefix: 数组列的前缀（如 "商品列表"）

    返回:
        聚合后的字典列表
    """
    grouped = defaultdict(lambda: defaultdict(list))

    for row in rows:
        # 提取父级数据（非数组列）
        parent_data = {k: v for k, v in row.items() if not k.startswith(array_key_prefix)}

        # 提取子级数据（数组列）
        child_data = {}
        for key, value in row.items():
            if key.startswith(array_key_prefix):
                # 移除前缀和点号，获取子级键名
                child_key = key[len(array_key_prefix) + 1:]
                child_data[child_key] = value

        # 生成唯一标识父级的键
        parent_key = tuple(sorted(parent_data.items()))

        # 将子级数据添加到对应父级的数组中
        grouped[parent_key]["parent"] = parent_data
        grouped[parent_key]["children"].append(child_data)

    # 转换为最终格式
    result = []
    for key in grouped:
        parent = grouped[key]["parent"]
        children = grouped[key]["children"]
        parent[array_key_prefix] = children  # 将子级数组添加到父级
        result.append(parent)

    return result

def group_list_items(rows, list_keys):
    """
    按父级键分组，将多行数据聚合为列表
    :param rows: 字典列表（每行数据）
    :param list_keys: 需聚合为列表的键（如 ["orders.id"]）
    """
    grouped = defaultdict(dict)
    for row in rows:
        key_parts = []
        list_part = None
        for lk in list_keys:
            if lk in row:
                # 拆分父级键和列表键（如 "orders.id" 拆分为 ["orders", "id"]）
                parent_keys, list_key = lk.rsplit(".", 1)
                parent_key = ".".join(parent_keys)
                key_parts.append((parent_key, list_key, row[lk]))
                del row[lk]  # 从当前行删除列表键，避免重复处理
        # 生成唯一分组键（基于非列表键）
        group_key = tuple(row.items())
        if group_key not in grouped:
            grouped[group_key] = row.copy()
        # 为每个列表键创建列表
        for parent_key, list_key, value in key_parts:
            if parent_key not in grouped[group_key]:
                grouped[group_key][parent_key] = {}
            if list_key not in grouped[group_key][parent_key]:
                grouped[group_key][parent_key][list_key] = []
            grouped[group_key][parent_key][list_key].append(value)
    return list(grouped.values())


# 处理 Unicode 转义序列
def unescape_unicode(df):
    for col in df.select_dtypes(include=['object']).columns:
        df[col] = df[col].apply(lambda x: x.encode('latin-1').decode('unicode_escape') if isinstance(x, str) else x)
    return df

def read_excel_to_objects(file_path: str, cls: Type[ExcelRow] = ExcelRow,
                          sheet_name: str = 0, header: int = 0,
                          data_transformers: Optional[Dict[str, Callable]] = None) -> List[ExcelRow]:
    """
    读取Excel文件并将每行转换为对象列表

    参数:
        file_path: Excel文件路径
        cls: 对象类，默认为ExcelRow
        sheet_name: 表名或索引
        header: 表头行号
        data_transformers: 数据转换函数映射，格式为 {列名: 转换函数}

    返回:
        对象列表
    """
    try:
        # 读取Excel文件
        df = pd.read_excel(file_path, sheet_name=sheet_name, header=header, engine='openpyxl')

        # 应用处理
        # df = unescape_unicode(df)
        # 处理缺失值：将NaN转换为None
        df = df.where(pd.notna(df), "")

        # 处理缺失值  问题的根源。当你传入 value=None 时，pandas 不知道如何填充缺失值，因此抛出错误
        # df = df.fillna(value=None)
        # 转为列表 of 字典（每行数据对应一个字典）
        rows = df.to_dict(orient="records")

        # 2. 定义需聚合为列表的键（如 orders.id 和 orders.amount）
        # list_keys = ["customerPhone.sort", "customerPhone.customerPhone", "customerPhone.customerName",
        #              "productList.adminPassword","productList.adminUser","productList.customerPhone","productList.endTime","productList.manager","productList.productId",
        #              "productList.productName","productList.projectAttr","productList.systemName",
        #              "schoolStageList.schoolStage","schoolStageList.schoolName"]
        list_keys = []
        # 指定需要聚合的数组字段
        array_fields = ["customerPhone", "productList", "schoolStageList","schoolStage","productList.customerPhone"]  # 示例：支持多级嵌套


        # 3. 分组聚合列表数据
        # grouped_rows = group_list_items(rows, list_keys)

        # grouped_rows = group_array_items(rows, "productList")
        grouped_rows = group_multiple_arrays(rows, array_fields)



        url = "https://cloudcampus.xinkaoyun.com:40002/api/operate/operateSchool/save"
        headers = {
            "Authorization": f"operate_e1269c15cf3849f2862d3d0a57eeb302_2adf652fd1e54ca29a1c974904207351",
            # "User-Agent": "MyApp/1.0"
        }

        # 4. 展平点分隔键为嵌套字典
        nested_data = [flatten_to_nested(row) for row in grouped_rows]
        # import json
        # jsonObject=json.dumps(nested_data, indent=2, ensure_ascii=False)
        for row in nested_data:
            # 发送请求
            request = send_post_request(url, row, headers)
            print(request)

        # 5. 输出结果（美化打印）
        import json
        #  json.dumps 默认会将非 ASCII 字符转换为 Unicode 转义序列。为了处理这种情况，
        #  我们可以设置 json.dumps 的参数 ensure_ascii=False，这样就可以直接输出中文而不会进行转义。
        print(json.dumps(nested_data, indent=2, ensure_ascii=False))



        # 存储结果对象列表
        objects = []

        # 遍历DataFrame的每一行
        for _, row in df.iterrows():
            # 将行数据转换为字典
            row_data = row.to_dict()

            # 应用数据转换
            if data_transformers:
                for col, transformer in data_transformers.items():
                    if col in row_data:
                        row_data[col] = transformer(row_data[col])

            # 创建对象并添加到列表
            obj = cls(data=row_data)
            objects.append(obj)

        return objects

    except Exception as e:
        print(f"读取Excel文件时出错: {e}")
        return []


def main():
    import sys
    print(sys.getdefaultencoding())
    # 示例：自定义数据类
    @dataclass
    class Product(ExcelRow):
        """产品数据类"""

        def get_display_name(self) -> str:
            """获取产品显示名称"""
            return f"{self.data.get('品牌')} {self.data.get('型号')}"

    # 示例：数据转换函数
    def convert_price(value):
        """将价格转换为浮点数"""
        try:
            return float(value)
        except (ValueError, TypeError):
            return None

    # Excel 文件路径（请替换为实际路径）
    file_path = 'school.xlsx'
    # file_path = 'school.csv'

    # 数据转换配置
    transformers = {
        '价格': convert_price,
        '库存': lambda x: int(x) if pd.notna(x) else 0
    }



    # 读取 Excel 并转换为对象列表
    products = read_excel_to_objects(
        file_path,
        cls=Product,
        data_transformers=transformers
    )

    # print(products)

    json_data = {"id":"","schoolName":"武强县东孙庄镇北堤小学","areaCascader":["130000000","131100000","131123000","131123103"],"schoolStage":["3"],"schoolStageList":[{"schoolStage":"3","schoolStageName":"小学"}],"gradeLevel":"5","gradeLevelName":"年级<班级","address":"","schoolDes":"","shouldAccessNum":1,"logo":"https://minio.xinkaoyun.com:9000/cloud-campus/operate/2025-05/common/287700f2d1294b7082533a0c99b8b13e_%E5%AD%A6%E6%A0%A1%E9%BB%98%E8%AE%A4logo.png","identification":"1","isTourClass":"","projectMark":"beidixx.wq.hsszhjy","teacherProduct":"cloud_campus","productList":[{"productId":"cloud_campus","productName":"云校园","adminUser":"admin","adminPassword":"zRaVrURvVVs5QqWgq3xq0w==","systemName":"武强县东孙庄镇北堤小学","manager":"e1269c15cf3849f2862d3d0a57eeb302","projectAttr":"1","endTime":"2026-5-15 8:14:18","remark":"","customerPhone":[{"sort":1,"customerPhone":"","customerName":""}]}],"provinceCode":"130000000","provinceName":"河北省","cityCode":"131100000","cityName":"衡水市","areaCode":"131123000","areaName":"武强县","streetCode":"131123103","streetName":"东孙庄镇","deptName":"","customerPhone":[{"sort":1,"customerPhone":"","customerName":""}]}

    # request_result = send_post_request(url, json_data,headers)

    # print(request_result)

    for product in products:
        result = asdict(product)
        print(result)
        # request_result = send_post_request(url, result, headers)
        # print(request_result)

    # 打印结果
    # if products:
    #     print(f"成功读取 {len(products)} 条记录")
    #     for product in products[:3]:  # 显示前3条记录
    #         print(f"产品: {product.get_display_name()}, 价格: {product.价格}")
    # else:
    #     print("未读取到数据")

    # 保存为CSV
    # if products:
    #     import csv
    #     csv_path = 'products.csv'
    #     with open(csv_path, 'w', newline='', encoding='utf-8') as csvfile:
    #         fieldnames = list(products[0].data.keys())
    #         writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    #         writer.writeheader()
    #         for product in products:
    #             writer.writerow(product.data)
    #     print(f"数据已保存到 {csv_path}")


if __name__ == "__main__":
    main()